package com.scale.lefu.lf_product_plugin

import android.content.Context
import android.os.Handler
import android.os.Looper
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.lefu.ppbase.PPBodyBaseModel
import com.lefu.ppbase.PPDeviceModel
import com.lefu.ppbase.PPSDKKit
import com.lefu.ppbase.PPScaleDefine
import com.lefu.ppbase.util.OnLogCallBack
import com.lefu.ppbase.vo.PPUnitType
import com.lefu.ppbase.vo.PPUserGender
import com.lefu.ppbase.vo.PPUserModel
import com.lefu.ppcalculate.PPBodyFatModel
import com.lefu.ppcalculate.PPCalculateKit
import com.peng.ppscale.PPBluetoothKit
import com.peng.ppscale.business.ble.listener.PPBleStateInterface
import com.peng.ppscale.business.ble.listener.PPDataChangeListener
import com.peng.ppscale.business.ble.listener.PPSearchDeviceInfoInterface
import com.peng.ppscale.business.device.DeviceManager
import com.peng.ppscale.business.state.PPBleSwitchState
import com.peng.ppscale.business.state.PPBleWorkState
import com.peng.ppscale.device.PeripheralApple.PPBlutoothPeripheralAppleController
import com.peng.ppscale.device.PeripheralTorre.PPBlutoothPeripheralTorreController
import com.peng.ppscale.search.PPSearchManager
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.EventChannel.EventSink
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result


/** LfProductPlugin */
class LfProductPlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler {

    private val methodChannelName = "lf_product_plugin"
    private val eventChannelName = "lf_product_plugin_event"

    private val appKey = "lefu05745512b926075a"
    private val appSecret = "knAS3KDlGojeQMvJAyGnDt35jtcj6vzbNuV5vyqOVyw="

    private lateinit var channel : MethodChannel
    private lateinit var eventChannel: EventChannel


    // 定义一个上下文
    private lateinit var context: Context
    private lateinit var eventSink: EventSink
    private lateinit var handler: Handler


    override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        context = flutterPluginBinding.applicationContext
        handler = Handler(Looper.getMainLooper())

        channel = MethodChannel(flutterPluginBinding.binaryMessenger, methodChannelName)
        channel.setMethodCallHandler(this)


        // eventChannel
        eventChannel = EventChannel(flutterPluginBinding.binaryMessenger, eventChannelName)
        eventChannel.setStreamHandler(this)
    }

    override fun onListen(arguments: Any?, events: EventSink) {
        eventSink = events

        /**
         * SDK日志打印
         * SDK日志写入文件，App内日志管理可控
         */
        PPSDKKit.setDebugLogCallBack(object : OnLogCallBack() {
            override fun logd(s: String?, s1: String?) {
//                handler.post {
//                    val map= HashMap<Any?, Any?>()
//                    map[s] = s1
//                    eventSink.success(map)
//                }
            }

            override fun logi(s: String?, s1: String?) {
//                handler.post {
//                    val map= HashMap<Any?, Any?>()
//                    map[s] = s1
//                    eventSink.success(map)
//                }
            }

            override fun logv(s: String?, s1: String?) {
//                handler.post {
//                    val map= HashMap<Any?, Any?>()
//                    map[s] = s1
//                    eventSink.success(map)
//                }
            }

            override fun logw(s: String?, s1: String?) {
//                handler.post {
//                    val map= HashMap<Any?, Any?>()
//                    map[s] = s1
//                    eventSink.success(map)
//                }
            }

            override fun loge(s: String?, s1: String?) {
//                handler.post {
//                    val map= HashMap<Any?, Any?>()
//                    map[s] = s1
//                    eventSink.success(map)
//                }
            }
        })
    }

    override fun onCancel(arguments: Any?) {

    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        val method = call.method
        val arguments = call.arguments

        when(method) {
            "getPlatformVersion" -> result.success("1.0.1")
            "getHelloWorld" -> result.success("hello android")
            "scan" -> {
                // 初始化
                initLf()
                var time = 30
                if (arguments != null) {
                    arguments as Map<String, Any>
                    if (arguments.containsKey("time")) {
                        time = (arguments.containsKey("time") as Number).toInt()
                    }
                }
                startScanDeviceList(time)


                // 开始扫描
                result.success("scan android")
            }
            "link" -> {
                arguments as Map<String, Any>
                val ppModel = mapToBean<PPDeviceModel>(arguments["device"] as Map<String, Any>)
                connect(ppModel)
                // 连接
                result.success(" link android")
            }
            "calculate4" -> {
                arguments as Map<String, Any>
                val height = (arguments["height"] as Number).toInt()
                val weight = (arguments["weight"] as Number).toDouble()
                val heartRate = (arguments["heartRate"] as Number).toInt()
                val impendance = (arguments["impendance"] as Number).toInt()
                val age = (arguments["age"] as Number).toInt()
                val gender = if ((arguments["gender"] as Number).toInt() == 0) PPUserGender.PPUserGenderFemale else PPUserGender.PPUserGenderMale
                val userModel =  PPUserModel.Builder()
                    .setAge(age)
                    .setHeight((height as Number).toInt())
                    .setSex(gender)
                    .setAthleteMode(false)
                    .setPregnantMode(false)
                    .setHeartRate((heartRate as Number).toInt())
                    .build()

                val deviceModel = PPDeviceModel("c1:c1:c1:c1", DeviceManager.FL_SCALE)//更换成你自己的设备蓝牙名称
                deviceModel.deviceCalcuteType = PPScaleDefine.PPDeviceCalcuteType.PPDeviceCalcuteTypeDirect
                val bodyBaseModel = PPBodyBaseModel()
                bodyBaseModel.weight = ((weight + 0.005) * 100).toInt()
                bodyBaseModel.impedance = (impendance as Number).toLong()
                bodyBaseModel.deviceModel = deviceModel
                bodyBaseModel.userModel = userModel
                bodyBaseModel.heartRate = heartRate
                bodyBaseModel.unit = PPUnitType.Unit_KG
                val ppBodyFatModel = PPBodyFatModel(bodyBaseModel)

                result.success(Gson().toJson(Msg(1, "success", ppBodyFatModel.ppFat, ppBodyFatModel.ppBMI)))
            }
            "calculate8" -> {
                arguments as Map<String, Any>
                val height = (arguments["height"] as Number).toInt()
                val weight = (arguments["weight"] as Number).toDouble()
                val heartRate = (arguments["heartRate"] as Number).toInt()
                val age = (arguments["age"] as Number).toInt()
                val gender = if ((arguments["gender"] as Number).toInt() == 0) PPUserGender.PPUserGenderFemale else PPUserGender.PPUserGenderMale

                val z20KhzLeftArmEnCode = (arguments["z20KhzLeftArmEnCode"] as Number).toLong()
                val z20KhzRightArmEnCode = (arguments["z20KhzRightArmEnCode"] as Number).toLong()
                val z20KhzLeftLegEnCode = (arguments["z20KhzLeftLegEnCode"] as Number).toLong()
                val z20KhzRightLegEnCode = (arguments["z20KhzRightLegEnCode"] as Number).toLong()
                val z20KhzTrunkEnCode = (arguments["z20KhzTrunkEnCode"] as Number).toLong()
                val z100KhzLeftArmEnCode = (arguments["z100KhzLeftArmEnCode"] as Number).toLong()
                val z100KhzRightArmEnCode = (arguments["z100KhzRightArmEnCode"] as Number).toLong()
                val z100KhzLeftLegEnCode = (arguments["z100KhzLeftLegEnCode"] as Number).toLong()
                val z100KhzRightLegEnCode = (arguments["z100KhzRightLegEnCode"] as Number).toLong()
                val z100KhzTrunkEnCode = (arguments["z100KhzTrunkEnCode"] as Number).toLong()

                //八电极计算类型
                val userModel = PPUserModel.Builder()
                    .setSex(gender) //gender
                    .setHeight(height as Int)//height 100-220
                    .setAge(age as Int)//age 10-99
                    .build()
                val deviceModel = PPDeviceModel("c1:c1:c1:c1", "CF577")//更换成你自己的设备蓝牙名称
                val calculateType = PPScaleDefine.PPDeviceCalcuteType.PPDeviceCalcuteTypeAlternate8//CF577系列
//                if (position == 0) {
//                    calcuteType = PPScaleDefine.PPDeviceCalcuteType.PPDeviceCalcuteTypeAlternate8//8电极算法, bhProduct=1--CF577
//                } else if (position == 1) {
//                    calcuteType = PPScaleDefine.PPDeviceCalcuteType.PPDeviceCalcuteTypeAlternate8_1//8电极算法，bhProduct =3--CF586
//                } else if (position == 2) {
//                    calcuteType = PPScaleDefine.PPDeviceCalcuteType.PPDeviceCalcuteTypeAlternate8_0//8电极算法，bhProduct =4--CF597
//                }
                deviceModel.deviceCalcuteType = calculateType
                val bodyBaseModel = PPBodyBaseModel()
                bodyBaseModel.weight = ((weight + 0.005) * 100).toInt()
                bodyBaseModel.deviceModel = deviceModel
                bodyBaseModel.userModel = userModel
                bodyBaseModel.heartRate = heartRate
                bodyBaseModel.z100KhzLeftArmEnCode = z100KhzLeftArmEnCode as Long
                bodyBaseModel.z100KhzLeftLegEnCode = z100KhzLeftLegEnCode as Long
                bodyBaseModel.z100KhzRightArmEnCode = z100KhzRightArmEnCode as Long
                bodyBaseModel.z100KhzRightLegEnCode = z100KhzRightLegEnCode as Long
                bodyBaseModel.z100KhzTrunkEnCode = z100KhzTrunkEnCode as Long
                bodyBaseModel.z20KhzLeftArmEnCode = z20KhzLeftArmEnCode as Long
                bodyBaseModel.z20KhzLeftLegEnCode = z20KhzLeftLegEnCode as Long
                bodyBaseModel.z20KhzRightArmEnCode = z20KhzRightArmEnCode as Long
                bodyBaseModel.z20KhzRightLegEnCode = z20KhzRightLegEnCode as Long
                bodyBaseModel.z20KhzTrunkEnCode = z20KhzTrunkEnCode as Long
                val fatModel = PPBodyFatModel(bodyBaseModel)

                result.success(Gson().toJson(Msg(1, "success", fatModel.ppFat, fatModel.ppBMI)))
            }
            else -> result.notImplemented()
        }
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
        eventChannel.setStreamHandler(null)
    }


    private fun initLf() {
        /*********************以下内容为SDK的配置项***************************************/
        /**
         *  SDK日志打印控制，true会打印
         */
        PPBluetoothKit.setDebug(false)

        /**
         * PPBluetoothKit 蓝牙库初始化 所需参数需要自行到开放平台自行申请，请勿直接使用Demo中的参数，
         * Demo中的参数仅供Demo使用
         * @param appKey App的标识
         * @param appSecret Appp的密钥
         * @param configPath 在开放平台下载相应的配置文件以.config结尾，并放到assets目录下，将config文件全名传给SDK
         */
        PPBluetoothKit.initSdk(context, appKey, appSecret, "lefu.config")
        /**
         * PPCalculateKit 计算库初始化
         */
        PPCalculateKit.initSdk(context)
    }

    // 扫描相关内容
    private var ppScale: PPSearchManager? = null
    private var searchDeviceInfoInterface: PPSearchDeviceInfoInterface? = null
    private val bleStateInterface = object : PPBleStateInterface() {
        override fun monitorMtuChange(ppDeviceModel: PPDeviceModel?) {
            ppBlutoothPeripheralTorreController?.getTorreDeviceManager()?.startMeasure {  }
        }
        /**
         * 蓝牙扫描和连接状态回调
         * Bluetooth scanning and connection status callback
         * @param ppBleWorkState 蓝牙状态标识/Bluetooth status indicator
         * @param deviceModel 设备对象/Device Object
         */
        override fun monitorBluetoothWorkState(ppBleWorkState: PPBleWorkState, deviceModel: PPDeviceModel?) {
            println("monitorBluetoothWorkState  ------- $ppBleWorkState  -------  $deviceModel")
            if (ppBleWorkState == PPBleWorkState.PPBleStateSearchCanceled) {
//                        Logger.d(getString(R.string.stop_scanning))
//                        tv_starts?.text = getString(R.string.bluetooth_status) + getString(R.string.stop_scanning)
            } else if (ppBleWorkState == PPBleWorkState.PPBleWorkSearchTimeOut) {
                val map= HashMap<String, Any>()
                map.put("find_time_out", true)
                eventSink.success(map)
//                        Logger.d(getString(R.string.scan_timeout))
//                        tv_starts?.text = getString(R.string.bluetooth_status) + getString(R.string.scan_timeout)
            } else if (ppBleWorkState == PPBleWorkState.PPBleWorkStateSearching) {
//                        Logger.d(getString(R.string.scanning))
//                        tv_starts?.text = getString(R.string.bluetooth_status) + getString(R.string.scanning)
            } else {

            }
        }

        /**
         * 系统蓝牙状态回调/System Bluetooth status callback
         * @param ppBleSwitchState 系统蓝牙状态标识/System Bluetooth status indicator
         */
        override fun monitorBluetoothSwitchState(ppBleSwitchState: PPBleSwitchState) {
            println("monitorBluetoothSwitchState -------  $ppBleSwitchState")
            if (ppBleSwitchState == PPBleSwitchState.PPBleSwitchStateOff) {

            } else if (ppBleSwitchState == PPBleSwitchState.PPBleSwitchStateOn) {

            }
        }
    }
    private fun startScanDeviceList(time: Int) {
        if (ppScale == null) {
            ppScale = PPSearchManager()
            searchDeviceInfoInterface = PPSearchDeviceInfoInterface { ppDeviceModel, data ->
                /**
                 *
                 * @param ppDeviceModel 设备对象
                 * @param data  广播数据
                 */
                // {"advLength":19,"deviceAccuracyType":"PPDeviceAccuracyTypePoint005","deviceCalcuteType":"PPDeviceCalcuteTypeAlternate","deviceConnectType":"PPDeviceConnectTypeDirect","deviceFuncType":32847,"deviceMac":"CF:E8:14:27:00:2E","deviceName":"HeartRate Scale","devicePower":-1,"devicePowerType":"PPDevicePowerTypeBattery","deviceProtocolType":"PPDeviceProtocolTypeV2","deviceSettingId":14,"deviceType":"PPDeviceTypeCF","deviceUnitType":"0,3,1","illumination":-1,"imgUrl":"https://unique.lefuenergy.com/prod/scale_img/default_no_border_black.png","macAddressStart":7,"mtu":244,"productModel":"CF516","rssi":-52,"sign":"FF","standardType":0}
                // 57FFCFE81427002ECF000000000000000001CE
                handler.post {
                    val map= HashMap<String, Any>()
                    map.put("find_new_device", ppDeviceModel.toMap())
                    eventSink.success(map)
                }
            }
        }
        //You can dynamically set the scan time in ms
        ppScale?.startSearchDeviceList(1000 * time, searchDeviceInfoInterface, bleStateInterface)
    }

    // 连接内容
    private var ppBlutoothPeripheralAppleController: PPBlutoothPeripheralAppleController? = null
    private var ppBlutoothPeripheralTorreController: PPBlutoothPeripheralTorreController? = null
    private var ppDateChangeListener: PPDataChangeListener = object : PPDataChangeListener {
        /**
         * 监听过程数据
         *
         * @param bodyBaseModel
         * @param deviceModel
         */
        override fun monitorProcessData(
            bodyBaseModel: PPBodyBaseModel?,
            deviceModel: PPDeviceModel?
        ) {
            println("------------------------------")
            handler.post {
                val map= HashMap<String, Any>()
                map.put("unlock_weight", bodyBaseModel?.weight?:0)
                eventSink.success(map)
            }
        }

        /**
         * 锁定数据
         *
         * @param bodyBaseModel
         */
        override fun monitorLockData(
            bodyBaseModel: PPBodyBaseModel?,
            deviceModel: PPDeviceModel?
        ) {
            handler.post {
                val map= HashMap<String, Any>()
                map.put("lock_weight", bodyBaseModel?.weight?:0)
                map.put("bodyBaseModel", bodyBaseModel.toMap())
                eventSink.success(map)
            }
        }

        /**
         * 超重
         */
        override fun monitorDataFail(
            bodyBaseModel: PPBodyBaseModel?,
            deviceModel: PPDeviceModel?
        ) {

        }
    }
    private fun connect(ppDeviceModel: PPDeviceModel) {
        println("-------------${ppDeviceModel.getDevicePeripheralType()}")
        when(ppDeviceModel.getDevicePeripheralType()) {
            PPScaleDefine.PPDevicePeripheralType.PeripheralApple -> {
                if (ppBlutoothPeripheralAppleController == null) {

                    ppBlutoothPeripheralAppleController = PPBlutoothPeripheralAppleController()

                    ppBlutoothPeripheralAppleController?.registDataChangeListener(ppDateChangeListener)
                }

                ppBlutoothPeripheralAppleController?.startConnect(ppDeviceModel, bleStateInterface)
            }

            PPScaleDefine.PPDevicePeripheralType.PeripheralTorre -> {
                if (ppBlutoothPeripheralTorreController == null) {

                    ppBlutoothPeripheralTorreController = PPBlutoothPeripheralTorreController()
                }

                ppBlutoothPeripheralTorreController?.getTorreDeviceManager()?.registDataChangeListener(ppDateChangeListener)
                ppBlutoothPeripheralTorreController?.startConnect(ppDeviceModel, bleStateInterface)
                // monitorMtuChange 之后开始测量
            }
            else -> {

            }
        }
    }


    inline fun <reified T> T.toMap(): Map<String, Any> {
        val gson = GsonBuilder().serializeNulls().create()
        val json = gson.toJson(this)
        return gson.fromJson(json, object : TypeToken<Map<String, Any>>() {}.type)
    }

    inline fun <reified T> mapToBean(map: Map<String, Any>): T {
        val gson = GsonBuilder().serializeNulls().create()
        val json = gson.toJson(map)
        return gson.fromJson(json, T::class.java)
    }
}

/// 原生传递事件类型
class LefuNativeEventType {
    companion object {
        /// 蓝牙状态变化
        const val  bluetoothStateChange = "lefu_bluetoothStateChange"

        /// 扫描设备回调
        const val  didFoundSurroundDevice = "lefu_didFoundSurroundDevice"

        /// 设备信息
        const val  deviceInfo = "deviceInfo";
        const val  peripheralInfo = "peripheralInfo"
    }
}

/// 原生传递类型
class LefuNativeMethodType {
    companion object {
        // 初始化sdk
        const val initSdk = "lefu_initSdk"

        /// 开启设备监听及蓝牙服务
        const val startService = "lefu_startService"

        /// 关闭备监听及蓝牙服务
        const val stopService = "lefu_stopService"

        /// 搜索周边设备
        const val startSearchArround = "lefu_searchSurroundDevice"

        /// 停止搜索设备
        const val stopSearchArround = "lefu_stopSurroundDevice"
    }
}

// ============     蓝牙相关 ================

/// 蓝牙状态
class LefuBluetoothState {
    companion object {
        const val off = 0 // 蓝牙关闭
        const val on = 1 // 蓝牙开启
        const val connected = 2 // 连接
        const val connectFailed = 3 // 连接失败
        const val disconnected = 4 // 断开连接
    }
}

data class Msg(val code: Int, val msg: String, val ppFat: Float, val ppBMI: Float)